﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.IO;

namespace MapEditor
{
    public class Node
    {
        /// <summary>
        /// List objects in node
        /// Non-leaf nodes must NOT cotain any objects
        /// </summary>
        public List<Object> ListObjects { get; set; }

        /// <summary>
        /// Bounding of node
        /// </summary>
        public Rectangle Rect { get; set; }

        /// <summary>
        /// List child node
        /// </summary>
        public Node[] ChildNode { get; set; }

        /// <summary>
        /// Node Id
        /// </summary>
        public double Id { get; set; }

        /// <summary>
        /// 
        /// </summary>
        private const int MinSizeUpdate = 400;
        private const int MinSizeRender = 800;

        /// <summary>
        /// 
        /// </summary>
        private const int Min = 3;
        /// <summary>
        /// Constructor
        /// </summary>
        public Node(Rectangle rect, double id)
        {
            ListObjects = new List<Object>();
            Rect = rect;
            ChildNode = null;
            Id = id;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="List"></param>
        public void BuildTree(bool isUpdate)
        {
            if(isUpdate)
            {
                if (Rect.Width <= MinSizeUpdate)
                {
                    return;
                }
            }
            else
            {
                if (Rect.Width <= MinSizeRender)
                {
                    return;
                }
            }
            

            if(ChildNode == null && ListObjects.Count > 0)
            {
                // Child Rect
                int size = Rect.Width / 2;
                Rectangle RectLT = new Rectangle(Rect.X, Rect.Y, size, size);
                Rectangle RectRT = new Rectangle(Rect.X + size, Rect.Y, size, size);
                Rectangle RectRB = new Rectangle(Rect.X + size, Rect.Y + size, size, size);
                Rectangle RectLB = new Rectangle(Rect.X, Rect.Y + size, size, size);

                // Create child nodes
                ChildNode = new Node[4];
                ChildNode[0] = new Node(RectLT, Id * 10 + 0);
                ChildNode[1] = new Node(RectRT, Id * 10 + 1);
                ChildNode[2] = new Node(RectRB, Id * 10 + 2);
                ChildNode[3] = new Node(RectLB, Id * 10 + 3);

                if (this.Id == 12)
                {
                    int i = 0;
                }

                foreach (Object o in ListObjects)
                {
                    Clip(o, ChildNode[0]);
                    Clip(o, ChildNode[1]);
                    Clip(o, ChildNode[2]);
                    Clip(o, ChildNode[3]);
                }
            }

           

            if (ChildNode != null)
            {
                ListObjects.Clear();      
                    
                ChildNode[0].BuildTree(isUpdate);
                ChildNode[1].BuildTree(isUpdate);
                ChildNode[2].BuildTree(isUpdate);
                ChildNode[3].BuildTree(isUpdate);
            }           
        }

        /// <summary>
        /// Clip object into node
        /// </summary>
        public void Clip(Object o, Node node)
        {
            Rectangle dest = Rectangle.Intersect(o.Rectangle, node.Rect);

            if (dest.Width < Min || dest.Height < Min) return;

            //1234567890p@#$%^&*()_ SAi============================================
            Object temp = new Object(o.Id, dest.X, dest.Y, o.Image, dest.Width, dest.Height);
            //=====================================================================
            temp.Number = o.Number;
            node.ListObjects.Add(temp);
        }

        /// <summary>
        /// Save
        /// </summary>
        public void Save(System.IO.StreamWriter file, int size)
        {
            // Save info Node: Id, Rect
            file.Write(Id + "\t" + Rect.X + "\t" + (size - Rect.Y) + "\t" + Rect.Width + "\t" + Rect.Height);

            // Save list Id object in node
            foreach (Object o in ListObjects)
            {
                if (o.Id == ID.Mario) continue;

                file.Write("\t" + o.Number);
            }
            file.WriteLine();

            if (ChildNode != null)
            {
                if (ChildNode[0] != null) ChildNode[0].Save(file, size);
                if (ChildNode[1] != null) ChildNode[1].Save(file, size);
                if (ChildNode[2] != null) ChildNode[2].Save(file, size);
                if (ChildNode[3] != null) ChildNode[3].Save(file, size);
            }
        }

        private bool IntersetRect(Rectangle A, Rectangle B)
        {
            Rectangle dest = Rectangle.Intersect(A, B);

            if (dest.Width == 0 && dest.Height == 0)
                return false;

            return true;
        }
    }
}
